package com.pactera.asmp.server.utils;

import com.pactera.asmp.server.common.annotations.FieldMeta;

import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: tlsserver
 * @Package com.pactera.asmp.server.utils
 * @ClassName: CompareUtil
 * @Description: 对象内被 FieldMeta 注解的属性，对角两对象属性值是否发生变化，把变化的属性整理返回
 * @Date 2020/06/08 17:29
 * @Author lvzhiqiang
 * @Version 1.0
 */
public class CompareUtil {


    /**
     * 获取两个对象同名属性内容不相同的列表
     * @param obj1 对象1
     * @param obj2 对象2
     * @return
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     */
    public static Map<String, Object> compareTwoClass(Object obj1, Object obj2) throws IllegalAccessException {
        Map<String, Object> resultMap = new HashMap<>();
        //获取对象的class
        Class<?> clazz1 = obj1.getClass();
        Class<?> clazz2 = obj2.getClass();
        //获取对象的属性列表
        Field[] field1 = clazz1.getDeclaredFields();
        Field[] field2 = clazz2.getDeclaredFields();
        //遍历属性列表field1
        for (int i = 0; i < field1.length; i++) {
            // 未标注 FieldMeta 时直接 next
            if(!field1[i].isAnnotationPresent(FieldMeta.class)) {
                continue;
            }
            String fieldName1 = getFieldName(field1[i]);

            //遍历属性列表field2
            for (int j = 0; j < field2.length; j++) {
                // 未标注 FieldMeta 时直接 next
                if (!field2[j].isAnnotationPresent(FieldMeta.class)) {
                    continue;
                }
                String fieldName2 = getFieldName(field2[j]);
                // 属性名不一致 next
                if (!fieldName1.equals(fieldName2)) {
                    continue;
                }
                field1[i].setAccessible(true);
                field2[j].setAccessible(true);

                Object objValue1 = field1[i].get(obj1);
                Object objValue2 = field2[j].get(obj2);

                //如果field1[i]属性值与field2[j]属性值内容不相同
                if (!compareTwo(objValue1, objValue2)) {
                    Map<String, Object> map2 = new HashMap<>();
                    map2.put("from", null == objValue1 ? "" : objValue1);
                    map2.put("to", null == objValue2 ? "" : objValue2);
                    resultMap.put(fieldName1, map2);
                }
                break;
            }
        }
        return resultMap;
    }

    /**
     * 获取属性名，若注解传入属性名则优先采用
     * @param field
     * @return
     */
    private static String getFieldName(Field field) {
        String metaAnnotationName = field.getAnnotation(FieldMeta.class).name();
        return StringUtils.isNotBlank(metaAnnotationName) ? metaAnnotationName : field.getName();
    }

    /**
     * 对比两个数据是否内容相同
     * @param object1
     * @param object2
     * @return
     */
    public static boolean compareTwo(Object object1, Object object2) {
        if(object1 == null) return object2 == null;
        return object1.equals(object2);
    }
}
